package com.pic.mgt.executer;

import org.springframework.dao.DataAccessException;

import com.pic.mgt.log.IgxLog;
import com.pic.mgt.unit.Redoable;
import com.pic.mgt.unit.Unit;

public abstract class UnitExecuter {
	protected Unit unit;
	
	public UnitExecuter() {
		
	}
	
	public synchronized void execute(Unit unit) {
		this.unit = unit;
		
		String redoStringForLog = "";
		if (Redoable.class.isInstance(unit)) {
			redoStringForLog = "(Redo)";
		}
		
		try {
			// ********************** Log **********************
			if (IgxLog.messageLog.isDebugMode()) {
				IgxLog.messageLog.debug(this, "Executing unit '{}'.{}" ,
						this.unit.getUnitName(), redoStringForLog);
			}
			// ********************** Log **********************
			
			// 更新資料庫狀態
			// throws DataAccessException
			updateStatusWhenBeginExecution();
			
			// throws UnitTypeExecutionException
			executeUnitType();
			
			// ********************** Log **********************
			if (IgxLog.messageLog.isInfoMode()) {
				IgxLog.messageLog.info(this, "Executing unit '{}' completed.{}",
						this.unit.getUnitName(), redoStringForLog);
			}
			// ********************** Log **********************
			
			// 更新資料庫狀態
			// throws DataAccessException
			updateStatusWhenExecutionSuccess();
		} catch (UnitTypeExecutionException e) {
			IgxLog.messageLog.error(this, e.getMessage());
			
			// 更新資料庫狀態
			try {
				updateStatusWhenExecutionfailed();
			} catch (DataAccessException e1) {
				// 無須做 log (子類別會做)
			}
		} catch (DataAccessException e1) {
			// 無須做 log (子類別會做)
		}
	}
	
	protected abstract void executeUnitType()
						throws UnitTypeExecutionException;
	
	/**
	 * 當開始執行配信動作前，須更新資料表的狀態。
	 */
	protected abstract void updateStatusWhenBeginExecution() throws DataAccessException;
	
	/**
	 * 當配信動作執行成功，須更新資料表的狀態。
	 */
	protected abstract void updateStatusWhenExecutionSuccess() throws DataAccessException;
	
	/**
	 * 當配信動作執行失敗，須更新資料表的狀態。
	 */
	protected abstract void updateStatusWhenExecutionfailed() throws DataAccessException;
}
